package com.googlecode.wickedforms.xvergabe.util;

import java.io.UnsupportedEncodingException;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;

public class ResourceUtil {

	/**
	 * Returns the string message represented by the given {@link ResourceMessage}
	 * object.
	 * 
	 * @param message
	 *          the {@link ResourceMessage} whose string representation to return
	 */
	public static String getMessageString(final ResourceMessage message) {
		final ResourceBundle bundle = getResourceBundle(message);
		final String key = getEnumKey(message);
		return toUtf8(bundle.getString(key));
	}

	/**
	 * Returns the string message represented by the given {@link ResourceMessage}
	 * object.
	 * 
	 * @param message
	 *          the {@link ResourceMessage} whose string representation to return
	 * @param locale
	 *          the locale in which to return the string message.
	 * @return the string message represented by the given {@link ResourceMessage}
	 *         object.
	 */
	public static String getMessageString(final ResourceMessage message, final Locale locale) {
		final ResourceBundle bundle = getResourceBundle(message, locale);
		final String key = getEnumKey(message);
		return toUtf8(bundle.getString(key));
	}

	/**
	 * Returns the formatted string message represented by the given
	 * {@link ResourceMessage} object.
	 * 
	 * @param message
	 *          the {@link ResourceMessage} whose string representation to return
	 * @param params
	 *          object array for {@link MessageFormat} params. May be null.
	 * @return the formatted string message represented by the given
	 *         {@link ResourceMessage} object.
	 */
	public static String getMessageString(final ResourceMessage message, final Object... params) {
		final ResourceBundle bundle = getResourceBundle(message);
		final String key = getEnumKey(message);
		final String stringMessage = bundle.getString(key);
		if (params == null) {
			return toUtf8(stringMessage);
		} else {
			return toUtf8(MessageFormat.format(stringMessage, params));
		}
	}

	/**
	 * Returns the formatted string message represented by the given
	 * {@link ResourceMessage} object.
	 * 
	 * @param message
	 *          the {@link ResourceMessage} whose string representation to return
	 * @param params
	 *          object array for {@link MessageFormat} params. May be null.
	 * @param locale
	 *          the locale in which to return the string message.
	 * @return the formatted string message represented by the given
	 *         {@link ResourceMessage} object.
	 */
	public static String getMessageString(final ResourceMessage message, final Locale locale, final Object... params) {
		final ResourceBundle bundle = getResourceBundle(message, locale);
		final String key = getEnumKey(message);
		final String stringMessage = bundle.getString(key);
		if (params == null) {
			return toUtf8(stringMessage);
		} else {
			return toUtf8(MessageFormat.format(stringMessage, params));
		}
	}

	/**
	 * Locates the {@link ResourceBundle} containing the message to log.
	 */
	protected static ResourceBundle getResourceBundle(final ResourceMessage message, final Locale locale) {
		if (locale == null) {
			return ResourceBundle.getBundle(message.getClass().getName());
		} else {
			return ResourceBundle.getBundle(message.getClass().getName(), locale);
		}
	}

	protected static ResourceBundle getResourceBundle(final ResourceMessage message) {
		return getResourceBundle(message, null);
	}

	/**
	 * Gets the name of the enum constant defined by the specified
	 * {@link LogMessage}.
	 */
	@SuppressWarnings({ "rawtypes" })
	public static String getEnumKey(final ResourceMessage message) {
		try {
			final Enum e = (Enum) message;
			return e.toString();
		} catch (final ClassCastException e) {
			throw new RuntimeException("LogMessage of type " + message.getClass() + " is not an enum type!");
		}
	}

	/**
	 * Converts a {@link ResourceBundle} to a {@link Properties} object.
	 * 
	 * @param resource
	 *          the {@link ResourceBundle} to convert.
	 * @return a {@link Properties} object containing the properties of the given
	 *         {@link ResourceBundle}.
	 */
	public static Properties convertResourceBundleToProperties(final ResourceBundle resource) {
		final Properties properties = new Properties();

		final Enumeration<String> keys = resource.getKeys();
		while (keys.hasMoreElements()) {
			final String key = keys.nextElement();
			properties.put(key, resource.getString(key));
		}

		return properties;
	}

	private static String toUtf8(final String latinString) {
		try {
			return new String(latinString.getBytes("ISO-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("Unsupported encoding!", e);
		}
	}

}
